This sample demonstrates how to write a simple Mac OS block device driver, in this case a RAM disk. It also demonstrates how to bundle a system extension (INIT), driver (DRVR) and control panel (cdev) in one file, to achieve maximum functionality while minimising the number of items in the System Folder.
This sample is a control panel, which installs a RAM disk. It compiles using Metrowerks C and is written almost entirely in C, along with a small assembly language DRVR header.
Using the Sample
User Level Operation
At the user level, the sample is very easy to use:
1. Drop a copy of the control panel “RamDisk (CW)” into your Control Panels folder.
2. Restart, ignoring any DebugStrs the first time the extension runs.
3. Then open the control panel, check the “Install ram disk at startup” checkbox and click on the RAM disk size slider to set the disk size.
4. Restart. The RAM disk should now appear on your desktop.
Sample Contents
The sample comes in five parts:
• RAMDiskINIT — This system extension (INIT) runs at startup time and is responsible for create the RAM disk globals, allocating space for the RAM disk in the system heap, installing and initialising the RAM Disk DRVR, adding a drive queue element for the RAM disk, and finally formatting the RAM disk.
• RAMDiskDRVR — This device driver (DRVR) is loaded by the INIT and appears in the Device Manager unit table. It is responsible for fielding the various Device Manager Read/Write/Control/Status requests expected of a block device driver.
• RAMDiskCDEV — This control panel (cdev) is the user interface to the RAM Disk Sample. It allows the user to configure various RAM disk settings, which is saves in the resource fork of the control panel. When the INIT loads, it gets these settings and uses them to create the appropriate RAM disk.
• TradDriverLoaderLib — This is a library for installing traditional Mac OS device drivers (DRVRs). This library was written to be reused by other device driver writers. If you look at no other part of this sample, you should still investigate using TradDriverLoaderLib. This sample only contains the parts of TradDriverLoaderLib that are needed for it to function. TradDriverLoaderLib is a sample in its own right, and you should get the full distribution of that sample for more details on its operation.
• ShowInitIcon — This is a library for showing icons on the screen while the machine boots. This sample only contains the parts of ShowInitIcon that are needed for it to function. ShowInitIcon is a sample in its own right, and you should get the full distribution of that sample for more details on its operation.
For a more detailed description of the files in the distribution, see the “Packing List” section towards the end of this document.
What You Need
This sample is built in CodeWarrior 11 using the C compiler.
I’ve had reports that the sample works just fine under CodeWarrior 10 as long you make sure the Code Model preference (in the “68K Processor” preference panel) is set to Small, however I make no guarantees.
How to Build
1. Open the “Metrowerks Build Script” AppleScript.
2. Run it.
3. Choose the folder containing the RAM Disk sample.
Implementation Issues
Asynchronicity
Because RAM is always available instantaneously, the RAM Disk DRVR has no need for asynchronous operation. This makes the code a lot easier to understand, but makes it less useful if you want to implement an asynchronous driver. If you’re implementing an asynchronous driver, you should also look at the AsyncDriverSample, available where all good sample code is sold.
Original Metrowerks Conversion
For the historically curious ONLY!
This sample was original written for MPW. The following notes were written by Brian Bechtel and discuss the process of converting the sample to Metrowerks.
• Added a main() routine to the driver to handle Metrowerks' startup code.
• Cleaned up various errors or warnings where Metrowerks was tighter than MPW or Symantec.
• Created a project file for the control panel. This project creates a code resource of type cdev, id -4064, which is a control panel. This project file is '3RamCDEV.µ'.
• I built the resource file, and named it '3RamCDEV.µ.rsrc'. This ensures that the resources will be automatically included when you build the control panel.
• Created a project file for the DRVR. This project is a code resource of type DRVR, id 48, which is the driver itself. Set the project so that the DRVR resource is merged into '3RamCDEV.µ.rsrc'.
• Created a project file for the INIT. This project is a code resource of type INIT, id 0, which will install the driver. Set the project so that the INIT resource is merged into '3RamCDEV.µ.rsrc'.
• I had to change the code slightly, because this driver was using some low memory globals directly. I now handle low memory accesses by using accessor functions. There was one problem; UnitNTryCnt was not defined. I created my own accessor functions for this low memory global. This is fixed in the Universal Headers starting with ETO 15.
• Recalculate BufPtr from the low memory global.
There is no way to set the driver flags in the driver header. You have to either use ResEdit to change them to the desired values, or set them explicitly in the driver. This sample driver sets the flags directly, in the DRVROpen() routine. [This part is now incorrect. The sample now uses a custom, assembly language, driver header, so the flags are now set there. Quinn]
Known Errors in Metrowerks C/C++ 1.0
For the historically curious ONLY!
MW C/C++ 68K 1.0 & earlier: The driver name ".RamDRVR" is put into the driver as {09}{00}.RamDRVR. I had to change this to {08}.RamDRVR{00} to be correct. This is what it should have generated. Use ResEdit. This is fixed in MW C/C++ 68K 1.0.1.
Packing List
This section gives a description of all the files included with this sample and what they contain:
• RamDiskCommon.h — Constants and types shared between the DRVR, INIT and cdev.
• RAMDiskDRVR.µ — A project file to build the RAM Disk DRVR.
• RAMDiskDriverMain.c — A C file that contains the main line of the disk image DRVR. This code replaces Metrowerks standard driver header. For the reasoning behind that, see the comments in the file.
• RamDRVR.c — The DRVR implementation.
• RAMDiskDRVR.out — The compiled DRVR.
• RAMDiskINIT.µ — A project file to build the RAM Disk INIT.
• RamINIT.c — Source code to the RAM Disk INIT.
• RAMDiskINIT.out — The compiled INIT.
• RAMDiskCDEV.µ — A project file to build the RAM Disk cdev. This project includes the RAMDiskINIT.out and RAMDiskDRVR.out. You use it to build the final file.
• RamCDev.c — Source code to the RAM Disk cdev.
• RAMDiskCDEV.rsrc — Resources for the RAM Disk cdev.
• RamDisk (CW) — The final output file.
• Metrowerks Build Script — An AppleScript to build the entire project.
• Documentation — A folder containing release notes that cover the history of the RAM Disk Sample.
• ShowInitIcon — A folder containing the parts of ShowInitIcon that are required for this build. If you’re interested in this technology, you should get the full distribution.
• TradDriverLoaderLib — A folder containing the parts of TradDriverLoaderLib that are required for this build. If you’re interested in this technology, you should get the full distribution.
Credits and Versions History
If you find any problems with this stuff, mail <DevSupport@apple.com> with “Attn: Quinn” as the first line of your mail and I’ll try to fix them up.
See the separate documents in the Documentation folder for a version history.
This sample was originally written by Gordon Sheridan. It was updated by Jim Luther. Brian Bechtel did the original conversion to Metrowerks at the WWDC ’94 Metrowerks coding lab. Quinn did the most recent code overhaul.